#ifndef Text_First
#define Text_First
#ifdef __GNUG__
#pragma interface
#endif

#include "Port.h"
#include "TextStyles.h"

class RegularExp;
class Command;
class Clipper;
class VObject;
class Mark;
class Iterator;
class MarkList;
class TextIter;
class Collection;
class VisualMark;
class LineDesc;

//---- abstract Text -----------------------------------------------------------

extern const int
	cTextInitCap,
	cEOT,
	cTabw;

const bool
	cSearchForward= TRUE,
	cSearchBackward= !cSearchForward,
	cPaginationChange= TRUE,
	cNoPaginationChange= !cPaginationChange;

const byte
	cTextPara  = 01,  // paragraph terminator
	cTextBreak = 02;  // break

//---- Text --------------------------------------------------------------------

class Text: public Object {
public:
	MetaDef(Text);
	void InitNew();

	~Text();

	//---- editing
	virtual void Insert(byte c, int from, int to);
	virtual void Cut(int from, int to);
	virtual void Paste(Text *t, int from, int to);
	virtual void Copy(Text* save, int from, int to);
	void Append(byte c);
	void Empty();

	// primitive for editing operations
	virtual void ReplaceRange(int from, int to, Text *src, int sfrom, int sto);
	virtual Text *MakeScratchText(byte *buf, int size);

	//---- converting
	virtual void InsertStr(int from, int to, byte *str, int len= -1);
	virtual void CopyInStr(byte *str, int strSize, int from, int to);
	void ReplaceWithStr(byte *str, int len= -1);
	const char *AsString();

	//---- accessing
	void SetFString(char *fmt, ...);
	Text *Save(int from, int to);
		// allocate new text object and copy the given range
	void SetDefTab(int tw);                 // set default tab width
	int GetDefTab();

	virtual byte& operator[](int i);
	virtual int Size();
	inline int End();
	bool IsEmpty();

	virtual int Search(RegularExp *rex, int *nMatched, int start= 0,
			int range= cMaxInt, bool dir= cSearchForward);
		// search rex and return position of match (-1 == no match)


	//---- style access
	virtual void ResetCurrentCharStyle();
	virtual void SetCharStyle(TxtCharProp mode, int from, int to, const CharStyleSpec &newStyle);
	virtual void SetParaStyle(TxtParaProp mode, int from, int to, const ParaDesc &props);
	virtual CharStyle *GetCharStyle(int at);
	virtual CharStyle *GetCurrentCharStyle();
	virtual ParaStyle *GetParaStyle(int at);

	void SetFont(Font *fd, int from= 0, int to= 0);
	Font *GetFont(int at= 0);

	//---- iterator
	virtual TextIter *MakeIterator(int from= 0, int to= cMaxInt, void *placement= 0);
		// abstract

	//---- text structure access
	bool IsParaStart(int at);
	bool IsParaEnd(int at);
	void GetWordRange(int at, int *start, int *end);
	void GetParaRange(int at, int *start, int *end);
	static bool IsBreak(byte ch);
	static bool IsPara(byte ch);
	int FindLastBreak(int from);
	int FindNextBreak(int from);

	//---- TextPainter
	virtual byte *GetLineAccess(byte **buf, int from, int to);
	virtual int GetNextFontChange(int at, CharStyle *&sp);

	//---- VisualMarks embedding
	virtual VisualMark *GetVisualMarkAt(int at);
	virtual byte GetMarkChar();
	virtual bool IsVisualMark(int at);

	//---- Marks
	void AddMark(Mark*);
	Mark *RemoveMark(Mark*);
	Iterator *GetMarkIter();
	MarkList *GetMarkList();

	//---- input/output
	virtual OStream& PrintOnAsPureText(OStream &s);
	virtual IStream& ReadFromAsPureText(IStream &s, long sizeHint= -1L);
	OStream& PrintOn(OStream&);
	IStream& ReadFrom(IStream&);

	//---- generic object methods
	u_long Hash();
	bool IsEqual(Object*);

	//---- inspecting
	void InspectorId(char*, int);

	//---- static
	static bool CheckRange(int max, int from, int to);

protected:
	Text();
	void Init();
	bool IsTerminated();

	virtual void SetFStringVL(char *fmt, va_list ap);
	virtual int GrowSize(int minSize);

	// overridden for optimized observing
	Collection *MakeObserverColl();
	Collection *GetObservers();
	void DestroyObserverColl();
	void SetObserverColl(Collection*);

protected:
	CharStyle *charStyle;
	ParaStyle *paraStyle;

private:
	MarkList *marks;
	Collection *observers;
	int tabWidth;
};

//---- character formatting properties -----------------------------------------

extern byte TextCharMap[];

inline bool Text::IsBreak(byte ch)
	{ return Iscntrl(ch) && (TextCharMap[ch] & cTextBreak); }

inline bool Text::IsPara(byte ch)
	{ return Iscntrl(ch) && (TextCharMap[ch] & cTextPara); }

inline int Text::End()
	{ return Size()-1; }

inline bool Text::IsTerminated()
	{ return (Size() > 0 && (*this)[Size()-1] == '\0'); }                   

inline bool Text::CheckRange(int max, int from, int to)
	{ return (to > max || from < 0 || from > to) ? FALSE: TRUE; }

//---- change protocol ---------------------------------------------------------
//     text is an abstract class defining methods to manage a buffer for
//     holding text. Together with the text there is a list of robust pointers
//     (called marks) into the text. Dependents of the Text classes are
//     notified by the observer mechanism and receive a change record as
//     described below as argument

enum eTextChanges {
	eTextChangedRange,
	eTextDeleted,
	eTextReplaced       // from,to=> replaced range, size=>size of inserted text
};
		
struct TextChanges {
	int from, to, size;
	bool pagination;
	TextChanges *operator()(int f, int t, int s= 0, bool p= cNoPaginationChange)
		{ from= f; to= t; size= s; pagination= p; return this; }
};

//---- abstract TextIter -------------------------------------------------------

class TextIter {
public:
	TextIter(Text *s, int from= 0, int to= cMaxInt);
	virtual ~TextIter();
		// abstract
	virtual int operator()(int *width= 0, LineDesc *l= 0);
		// abstract
	virtual void Reset(Text *s, int from= 0, int to= cMaxInt);
	virtual int Token(int *width, LineDesc* l= 0);
		// return next token and width, abstract
	virtual int GetPos();
	virtual Font *FontAt(int);
	virtual int GetLastPos();
		// get last position
	virtual void SetPos(int newPos);
	virtual int Unget();
		// unget last token

protected:
	int ce, upto, unget;
	Text *ct;
};

//---- AutoTextIter ------------------------------------------------------------

class AutoTextIter {
	TextIter *ti;
	char space[64];
public:
	AutoTextIter(Text *t, int from= 0, int to= cMaxInt);
	AutoTextIter(TextIter *tip);
	~AutoTextIter();
	int operator()(int *width= 0, LineDesc *l= 0);
	TextIter *operator->();
	operator TextIter*();
};

inline AutoTextIter::AutoTextIter(Text *t, int from, int to)
	{ ti= t->MakeIterator(from, to, space); }
inline AutoTextIter::AutoTextIter(TextIter *tip)
	{  ti= tip; }
inline int AutoTextIter::operator()(int *width, LineDesc *l)
	{ return ti->operator()(width, l); }
inline TextIter *AutoTextIter::operator->()
	{ return ti; }
inline AutoTextIter::operator TextIter*()
	{ return ti; }

#endif

